#include "StdAfx.h"
#include "Markup.h"
#include "MarkupNode.h"

CMarkupNode::CMarkupNode(void):m_pOwner(NULL)
{
}

CMarkupNode::~CMarkupNode(void)
{
}

CMarkupNode::CMarkupNode(CMarkup* pOwner, int iPos) : m_pOwner(pOwner), m_iPos(iPos), m_nAttributes(0)
{
}

CMarkupNode CMarkupNode::GetSibling()
{
	if( m_pOwner == NULL ) return CMarkupNode();
	ULONG iPos = m_pOwner->m_pElements[m_iPos].iNext;
	if( iPos == 0 ) return CMarkupNode();
	return CMarkupNode(m_pOwner, iPos);
}

bool CMarkupNode::HasSiblings() const
{
	if( m_pOwner == NULL ) return false;
	ULONG iPos = m_pOwner->m_pElements[m_iPos].iNext;
	return iPos > 0;
}

CMarkupNode CMarkupNode::GetChild()
{
	if( m_pOwner == NULL ) return CMarkupNode();
	ULONG iPos = m_pOwner->m_pElements[m_iPos].iChild;
	if( iPos == 0 ) return CMarkupNode();
	return CMarkupNode(m_pOwner, iPos);
}

CMarkupNode CMarkupNode::GetChild(LPCTSTR pstrName)
{
	if( m_pOwner == NULL ) return CMarkupNode();
	ULONG iPos = m_pOwner->m_pElements[m_iPos].iChild;
	while( iPos != 0 ) {
		if( _tcscmp(m_pOwner->m_pstrXML + m_pOwner->m_pElements[iPos].iStart, pstrName) == 0 ) {
			return CMarkupNode(m_pOwner, iPos);
		}
		iPos = m_pOwner->m_pElements[iPos].iNext;
	}
	return CMarkupNode();
}

bool CMarkupNode::HasChildren() const
{
	if( m_pOwner == NULL ) return false;
	return m_pOwner->m_pElements[m_iPos].iChild != 0;
}

CMarkupNode CMarkupNode::GetParent()
{
	if( m_pOwner == NULL ) return CMarkupNode();
	ULONG iPos = m_pOwner->m_pElements[m_iPos].iParent;
	if( iPos == 0 ) return CMarkupNode();
	return CMarkupNode(m_pOwner, iPos);
}

bool CMarkupNode::IsValid() const
{
	return m_pOwner != NULL;
}

LPCTSTR CMarkupNode::GetName() const
{
	if( m_pOwner == NULL ) return NULL;
	return m_pOwner->m_pstrXML + m_pOwner->m_pElements[m_iPos].iStart;
}

LPCTSTR CMarkupNode::GetValue() const
{
	if( m_pOwner == NULL ) return NULL;
	return m_pOwner->m_pstrXML + m_pOwner->m_pElements[m_iPos].iData;
}

LPCTSTR CMarkupNode::GetAttributeName(int iIndex)
{
	if( m_pOwner == NULL ) return NULL;
	if( m_nAttributes == 0 ) _MapAttributes();
	if( iIndex < 0 || iIndex >= m_nAttributes ) return _T("");
	return m_pOwner->m_pstrXML + m_aAttributes[iIndex].iName;
}

LPCTSTR CMarkupNode::GetAttributeValue(int iIndex)
{
	if( m_pOwner == NULL ) return NULL;
	if( m_nAttributes == 0 ) _MapAttributes();
	if( iIndex < 0 || iIndex >= m_nAttributes ) return _T("");
	return m_pOwner->m_pstrXML + m_aAttributes[iIndex].iValue;
}

LPCTSTR CMarkupNode::GetAttributeValue(LPCTSTR pstrName)
{
	if( m_pOwner == NULL ) return NULL;
	if( m_nAttributes == 0 ) _MapAttributes();
	for( int i = 0; i < m_nAttributes; i++ ) {
		if( _tcscmp(m_pOwner->m_pstrXML + m_aAttributes[i].iName, pstrName) == 0 ) return m_pOwner->m_pstrXML + m_aAttributes[i].iValue;
	}
	return _T("");
}

bool CMarkupNode::GetAttributeValue(int iIndex, LPTSTR pstrValue, SIZE_T cchMax)
{
	if( m_pOwner == NULL ) return false;
	if( m_nAttributes == 0 ) _MapAttributes();
	if( iIndex < 0 || iIndex >= m_nAttributes ) return false;
	_tcsncpy(pstrValue, m_pOwner->m_pstrXML + m_aAttributes[iIndex].iValue, cchMax);
	return true;
}

bool CMarkupNode::GetAttributeValue(LPCTSTR pstrName, LPTSTR pstrValue, SIZE_T cchMax)
{
	if( m_pOwner == NULL ) return false;
	if( m_nAttributes == 0 ) _MapAttributes();
	for( int i = 0; i < m_nAttributes; i++ ) {
		if( _tcscmp(m_pOwner->m_pstrXML + m_aAttributes[i].iName, pstrName) == 0 ) {
			_tcsncpy(pstrValue, m_pOwner->m_pstrXML + m_aAttributes[i].iValue, cchMax);
			return true;
		}
	}
	return false;
}

int CMarkupNode::GetAttributeCount()
{
	if( m_pOwner == NULL ) return 0;
	if( m_nAttributes == 0 ) _MapAttributes();
	return m_nAttributes;
}

bool CMarkupNode::HasAttributes()
{
	if( m_pOwner == NULL ) return false;
	if( m_nAttributes == 0 ) _MapAttributes();
	return m_nAttributes > 0;
}

bool CMarkupNode::HasAttribute(LPCTSTR pstrName)
{
	if( m_pOwner == NULL ) return false;
	if( m_nAttributes == 0 ) _MapAttributes();
	for( int i = 0; i < m_nAttributes; i++ ) {
		if( _tcscmp(m_pOwner->m_pstrXML + m_aAttributes[i].iName, pstrName) == 0 ) return true;
	}
	return false;
}

void CMarkupNode::_MapAttributes()
{
	m_nAttributes = 0;
	LPCTSTR pstr = m_pOwner->m_pstrXML + m_pOwner->m_pElements[m_iPos].iStart;
	LPCTSTR pstrEnd = m_pOwner->m_pstrXML + m_pOwner->m_pElements[m_iPos].iData;
	pstr += _tcslen(pstr) + 1;
	while( pstr < pstrEnd ) {
		m_pOwner->_SkipWhitespace(pstr);
		m_aAttributes[m_nAttributes].iName = pstr - m_pOwner->m_pstrXML;
		pstr += _tcslen(pstr) + 1;
		if( *pstr++ != '\"' ) return;
		m_aAttributes[m_nAttributes++].iValue = pstr - m_pOwner->m_pstrXML;
		if( m_nAttributes >= MAX_XML_ATTRIBUTES ) return;
		pstr += _tcslen(pstr) + 1;
	}
}

